package io.itit.smartjdbc.provider.impl.pgsql;

import io.itit.smartjdbc.SmartDataSource;
import io.itit.smartjdbc.model.Model;
import io.itit.smartjdbc.model.ModelColumn;
import io.itit.smartjdbc.model.ModelIndex;
import io.itit.smartjdbc.provider.CreateTableProvider;
import io.itit.smartjdbc.provider.entity.SqlBean;

/**
 * 
 * @author skydu
 *
 */
public class PgsqlCreateTableProvider extends CreateTableProvider {
	//
	public PgsqlCreateTableProvider(SmartDataSource smartDataSource) {
		super(smartDataSource);
	}

	//
	@Override
	public SqlBean build() {
		StringBuilder sql = new StringBuilder();
		Model model = createTable.model;
		// 添加表基本信息
		sql.append("CREATE TABLE ");
		if (model.schema != null && !model.schema.isEmpty()) {
			sql.append(model.schema).append(".");
		}
		sql.append(model.tableName).append(" (\n");

		// 添加字段信息
		for (ModelColumn column : model.columnList) {
			sql.append("    ").append(column.name).append(" ").append(getColumnType(column)).append(" ");
			if (column.notnull) {
				sql.append("NOT NULL ");
			}
			if (column.defaultValue != null) {
				sql.append("DEFAULT ").append(formatDefaultValue(column.defaultValue)).append(" ");
			}
			if (column.comment != null && !column.comment.isEmpty()) {
				sql.append("COMMENT '").append(column.comment).append("' ");
			}
			sql.append(",\n");
		}

		// 添加主键信息
		if (model.primaryKey != null && !model.primaryKey.columnList.isEmpty()) {
			sql.append("    PRIMARY KEY (").append(String.join(", ", model.primaryKey.columnList)).append("),\n");
		}

		// 添加索引信息
		for (ModelIndex index : model.indexList) {
			sql.append("    ");
			if (ModelIndex.TYPE_唯一索引.equals(index.type)) {
				sql.append("UNIQUE ");
			}
			sql.append("INDEX ").append(index.name).append(" (").append(String.join(", ", index.columnList))
					.append("),\n");
		}

		// 移除最后一个逗号并添加结束括号
		if (sql.charAt(sql.length() - 2) == ',') {
			sql.delete(sql.length() - 2, sql.length());
		}

		sql.append("\n);");
		return SqlBean.build(sql.toString());
	}

	private static String getColumnType(ModelColumn column) {
	    switch (column.type) {
	        case VARCHAR:
	            return "VARCHAR(" + column.length + ")";
	        case INT:
	            return "INTEGER";  // PostgreSQL 使用 INTEGER 作为 INT 类型的映射
	        case BIGINT:
	            return "BIGINT";   // PostgreSQL 使用 BIGINT 来表示大整数
	        case TINYINT:
	            return "SMALLINT"; // PostgreSQL 没有 TINYINT，使用 SMALLINT 替代
	        case SMALLINT:
	            return "SMALLINT"; // PostgreSQL 中 SMALLINT 对应 2 字节整数
	        case MEDIUMINT:
	            return "INTEGER";  // PostgreSQL 没有 MEDIUMINT，使用 INTEGER 替代
	        case LONG:
	            return "BIGINT";   // LONG 映射为 BIGINT
	        case FLOAT:
	            return "REAL";     // PostgreSQL 中浮点类型使用 REAL
	        case DOUBLE:
	            return "DOUBLE PRECISION";  // DOUBLE PRECISION 用于双精度浮点数
	        case BIGDECIMAL:
	            return "NUMERIC";  // PostgreSQL 使用 NUMERIC 或 DECIMAL 来表示高精度浮点数
	        case CHAR:
	            return "CHAR(" + column.length + ")";
	        case TEXT:
	            return "TEXT";     // TEXT 是 PostgreSQL 中的可变长度字符串
	        case MEDIUMTEXT:
	            return "TEXT";     // PostgreSQL 中没有 MEDIUMTEXT，使用 TEXT 替代
	        case DATE:
	            return "DATE";     // PostgreSQL 中的 DATE 类型
	        case TIMESTAMP:
	            return "TIMESTAMP" + (column.length > 0 ? "(" + column.length + ")" : "");  // 支持时间戳精度
	        case JSONB:
	            return "JSONB";    // PostgreSQL 支持 JSONB 类型
	        case TEXT_ARRAY:
	            return "TEXT[]";   // 数组类型 TEXT[]
	        case VARCHAR_ARRAY:
	            return "VARCHAR[]"; // 数组类型 VARCHAR[]
	        case INT_ARRAY:
	            return "INTEGER[]"; // 数组类型 INTEGER[]
	        case FLOAT_ARRAY:
	            return "REAL[]";   // 数组类型 REAL[]
	        case BOOL:
	            return "BOOLEAN";  // 布尔类型
	        case LTREE:
	            return "LTREE";    // PostgreSQL 特有的 LTREE 类型，用于存储树形数据
	        // 如果没有匹配的类型，可以返回类型的名称
	        default:
	            return column.type.name();
	    }
	}
	// 格式化默认值
	private static String formatDefaultValue(Object defaultValue) {
		if (defaultValue instanceof String) {
			return "'" + defaultValue + "'";
		} else if (defaultValue instanceof Boolean) {
			return (Boolean) defaultValue ? "TRUE" : "FALSE";
		}
		return defaultValue.toString();
	}

}
